package com.william.jdbcplus.core.generator;

import com.william.jdbcplus.common.constant.TableConstant;
import com.william.jdbcplus.core.generator.meta.EntityTableColumnInfo;
import com.william.jdbcplus.core.generator.meta.EntityTableInfo;
import com.william.jdbcplus.core.toolkit.DateUtil;
import com.william.jdbcplus.core.toolkit.StringPool;

import java.util.Date;

/**
 * 实体代码生成器
 */
public class EntityGenerator {

    public static String generator(GeneratorConfig config, EntityTableInfo entity) {
        StringBuffer code = new StringBuffer();
        code.append(String.format("package %s.%s.entity;", config.getPackageName(), config.getModuleName()));
        code.append(StringPool.NEWLINE);

        code.append(StringPool.NEWLINE).append("import com.william.jdbcplus.annotation.TableColumn;");
        code.append(StringPool.NEWLINE).append("import com.william.jdbcplus.annotation.TableId;");
        code.append(StringPool.NEWLINE).append("import com.william.jdbcplus.annotation.TableName;");
        code.append(StringPool.NEWLINE).append("import com.william.jdbcplus.entity.Entity;");
        code.append(StringPool.NEWLINE).append("import com.william.jdbcplus.enums.IdType;");
        code.append(StringPool.NEWLINE).append("import lombok.Data;");
        code.append(StringPool.NEWLINE).append("import lombok.EqualsAndHashCode;");
        code.append(StringPool.NEWLINE).append("import lombok.NoArgsConstructor;");
        code.append(StringPool.NEWLINE);

        boolean hasBigDecimal = entity.getColumnList().stream().anyMatch(e -> e.getAttrType().equals("BigDecimal"));
        if (hasBigDecimal) {
            code.append(StringPool.NEWLINE).append("import java.math.BigDecimal;");
        }

        boolean hasBigInt = entity.getColumnList().stream().anyMatch(e -> e.getAttrType().equals("BigInteger"));
        if (hasBigInt) {
            code.append(StringPool.NEWLINE).append("import java.math.BigInteger;");
        }

        boolean hasDate = entity.getColumnList().stream().anyMatch(e -> e.getAttrType().equals("Date"));
        if (hasDate) {
            code.append(StringPool.NEWLINE).append("import java.util.Date;");
        }

        code.append(StringPool.NEWLINE);
        code.append(StringPool.NEWLINE).append("/**");
        code.append(StringPool.NEWLINE).append(String.format("* %s", entity.getTableRemarks()));
        code.append(StringPool.NEWLINE).append(" * ");
        code.append(StringPool.NEWLINE).append(String.format(" * @author %s", config.getAuthor()));
        code.append(StringPool.NEWLINE).append(String.format(" * @date %s", DateUtil.formatDateTime(new Date())));
        code.append(StringPool.NEWLINE).append(" */ ");
        code.append(StringPool.NEWLINE).append("@Data");
        code.append(StringPool.NEWLINE).append("@NoArgsConstructor");
        code.append(StringPool.NEWLINE).append(String.format("@TableName(value = \"%s\", remarks = \"%s\")", entity.getTableName(), entity.getTableRemarks()));
        code.append(StringPool.NEWLINE).append(String.format("public class %s implements Entity {", entity.getEntityName()));

        //主键
        code.append(StringPool.NEWLINE);

        if (entity.getKeyInfo() != null) {
            String idType = "";
            if (entity.getKeyInfo().getAttrType().equals("String")) {
                idType = ", type = IdType.GUID";
            } else {
                idType = ", type = IdType.NUMBER";
            }

            String size = "";
            if (entity.getKeyInfo().getSize() != TableConstant.SIZE) {
                size = String.format(", size = %s", entity.getKeyInfo().getSize());
            }

            code.append(StringPool.NEWLINE).append(StringPool.TAB).append(String.format("@TableId(value = \"%s\", remarks = \"%s\"%s%s)", entity.getKeyInfo().getLowerColumnName(), entity.getKeyInfo().getRemarks(), idType, size));
            code.append(StringPool.NEWLINE).append(StringPool.TAB).append(String.format("private %s %s;", entity.getKeyInfo().getAttrType(), entity.getKeyInfo().getLowerAttrName()));
        }

        for (EntityTableColumnInfo columnInfo : entity.getColumnList()) {
            code.append(StringPool.NEWLINE);
            String size2 = "";
            if (columnInfo.getSize() != TableConstant.SIZE && !columnInfo.getAttrType().equals("Date")) {
                size2 = String.format(", size = %s", columnInfo.getSize());
            }
            String digits = "";
            if (columnInfo.getDigits() != TableConstant.DIGITS) {
                digits = String.format(", digits = %s", columnInfo.getDigits());
            }
            String nullable = "";
            if (columnInfo.isNullable() != TableConstant.NULLABLE) {
                digits = String.format(", nullable = %s", columnInfo.isNullable());
            }

            code.append(StringPool.NEWLINE).append(StringPool.TAB).append(String.format("@TableColumn(value = \"%s\", remarks = \"%s\"%s%s%s)", columnInfo.getLowerColumnName(), columnInfo.getRemarks(), size2, digits, nullable));
            code.append(StringPool.NEWLINE).append(StringPool.TAB).append(String.format("private %s %s;", columnInfo.getAttrType(), columnInfo.getLowerAttrName()));
        }

        code.append(StringPool.NEWLINE).append("}");
        String codeText = code.toString();
        return codeText;
    }
}